package thread;

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读写锁demo
 * 
 * 多个读锁不互斥，读锁和写锁互斥，写锁和写锁互斥
 *
 */
public class ReadWriteLockDemo {
	/** 
	 * main: 三个线程读，三个线程写<br/> 
	 * @author xiongfei
	 * @param args
	 */
	public static void main(String[] args) {
		final ReadWrite readwrite = new ReadWrite();

		for (int i = 0; i < 3; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					while (true) {
						readwrite.read();
					}
				}
			}).start();
		}

		for (int i = 0; i < 3; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					while (true) {
						readwrite.write(new Random().nextInt(5000));
					}
				}
			}).start();
		}
	}
}

class ReadWrite {

	// 共享数据
	private Object data;
	// 要操作同一把锁上的读或写锁
	ReadWriteLock lock = new ReentrantReadWriteLock();

	/** 
	 * read:读方法. <br/> 
	 * @author xiongfei
	 */
	public void read() {
		// 上读锁
		lock.readLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + " ready to read data");
			Thread.sleep(new Random().nextInt(5000));
			System.out.println(Thread.currentThread().getName() + " have read data=" + data);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			// 解锁
			lock.readLock().unlock();
		}
	}

	/** 
	 * write:写方法 <br/> 
	 * @author xiongfei
	 * @param data
	 */
	public void write(Object data) {
		// 上写锁
		lock.writeLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + " ready to write data");
			Thread.sleep(new Random().nextInt(5000));
			System.out.println(Thread.currentThread().getName() + " have write data=" + data);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		this.data = data;
		// 解锁
		lock.writeLock().unlock();
	}
}
